package com.gao.d_selector.b;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * 该例子演示了nio的基本编写方式，此例子中并不涉及多路复用
 * @author gao
 * @time 2020/06/27 11:01:08
 */
public class Server {
    public static void main(String[] args) {
        try {
            List<SocketChannel> socketChannelList = new ArrayList<>();
            ByteBuffer buf = ByteBuffer.allocate(16);

            ServerSocketChannel ssc = ServerSocketChannel.open();
            ssc.bind(new InetSocketAddress("127.0.0.1", 8888));
            ssc.configureBlocking(false);

            System.out.println("The server has been started");

            while (true) {
                // 防止测试结果被刷屏
                try {
                    Thread.sleep(1000);
                } catch (Exception e) {
                    e.printStackTrace();
                }

                SocketChannel socketChannel = ssc.accept();
                if (socketChannel == null) {
                    System.out.println(Thread.currentThread().getName() + ": no client available");
                } else {
                    System.out.println(Thread.currentThread().getName() + ": here comes a new client， " + socketChannel.getRemoteAddress());
                    socketChannel.configureBlocking(false);
                    socketChannelList.add(socketChannel);
                }

                Iterator<SocketChannel> it = socketChannelList.iterator();

                while (it.hasNext()) {
                    try {
                        SocketChannel channel = it.next();
                        int n = channel.read(buf);
                        if (n < 1) {
                            System.out.println(Thread.currentThread().getName() + ": no data from " + channel.getRemoteAddress());
                        } else {
                            buf.flip();
                            System.out.println(Thread.currentThread().getName() + ": read data from " + channel.getRemoteAddress() + ", the data is: " + new String(buf.array()));
                            buf.clear();
                        }
                    } catch (IOException e) {
                        // 当前轮询到的客户端断开连接
                        e.printStackTrace();
                        // 删除断开连接的客户端
                        it.remove();
                    }
                }
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

/*
    这个例子就是非阻塞IO的体现了，在accept()和read()上是非阻塞的，也就是说目前这种写法，在accept接收不到客户端，以及read无法读取到数据时都是不阻塞的，
    那么问题也就很明显了：cpu会有很大的几率处于“空转”状态！ 例子跑起来，看看Server端的输出就知道了，cpu是不停歇地执行Server的循环逻辑的！
*/